package tools;

import annotation.ArgEntry;
import annotation.Args;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Optional;

public class AnnotationUtil {
    public static <T extends Annotation> Optional<T> getAnnotation(AnnotatedElement tClass, Class<T> annotationType){
        if (tClass.isAnnotationPresent(annotationType)){
            return Optional.of(tClass.getAnnotation(annotationType));
        }
        return Optional.empty();
    }

    public static ArgEntry getArg(Args args, String name){
        return getArgOptional(args, name).orElse(null);
    }

    public static Optional<ArgEntry> getArgOptional(Args args,String name){
        if (args!=null) {
            for (ArgEntry entry : args.value()) {
                if (entry.name().equals(name)){
                    return Optional.of(entry);
                }
            }
        }
        return Optional.empty();
    }

    public static <T> T getArgValue(Args args,String name){
        return (T)getArgValue(getArg(args, name));
    }

    public static <T> Optional<T> getArgValueOptional(Args args,String name){
        return getArgOptional(args, name).flatMap(AnnotationUtil::getArgValueOptional);
    }

    public static <T> Optional<T> getArgValueOptional(ArgEntry argEntry){
        return Optional.ofNullable((T)getArgValue(argEntry));
    }

    public static Object getArgValue(ArgEntry argEntry){
        if (argEntry == null) {
            return null;
        }
        switch (argEntry.type()){
            case INT:
                return argEntry.intValue();
            case LONG:
                return argEntry.longValue();
            case FLOAT:
                return argEntry.floatValue();
            case DOUBLE:
                return argEntry.doubleValue();
            case STRING:
                return argEntry.stringValue();
            case CLASS:
                return argEntry.classValue();
            case STRING_ARRAY:
                return argEntry.stringArray();
        }
        return argEntry.stringValue();
    }
}
